import json, os, re, time, hmac, hashlib, base64
import requests, redis, jinja2
from lxml import etree
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client


API_KEY = '0b2bdeda43b5688921839c8ecb20399b'
redis_instance = redis.Redis(host='localhost', port=6379, db=0)
config = CosConfig(Region='ap-guangzhou', SecretId='AKIDMnxCUBusqPdqCwrALvDwxW1TEcWxlUn6', SecretKey='JdATOWS43FXKwZCZX4iyaElMzk788LWD')  # 获取配置对象
client = CosS3Client(config)


def cache(wrap_func):
    def real(movie_id):
        movie_cache = redis_instance.get('movie_{}'.format(movie_id))
        if movie_cache:
            return json.loads(movie_cache)
        else:
            movie = wrap_func(movie_id)
            redis_instance.set('movie_{}'.format(movie_id), json.dumps(movie)) # 不加json.dumps, 存的是二进制序列化的bytes, 而不是json string
            return movie
    return real


def fetch_latest_movies(limit=20):
    return [
        json.loads(fetch_movie_detail(movie['id']))
            for movie in requests.get('https://api.douban.com/v2/movie/in_theaters?count={}'.format(limit)).json()['subjects']
    ]


@cache
def fetch_movie_detail(movie_id):
    print("fetching movie {}".format(movie_id))
    return requests.get('https://api.douban.com/v2/movie/subject/{}?apikey={}'.format(movie_id, API_KEY)).text


def get_jinja_template(html_name):
    templateLoader = jinja2.FileSystemLoader(searchpath="./")
    templateEnv = jinja2.Environment(loader=templateLoader)
    return templateEnv.get_template(html_name)


def generate_local_html(html_name, html_content):
    path = './site/movie/{}'.format(html_name)
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, 'wb') as html_handler:
        html_handler.write(bytes(html_content, 'utf8'))


class SiteMap:
    header = '<?xml version="1.0" encoding="UTF-8"?>\n'
    xml_tree = None
    site_map_path = None

    def __init__(self, site_map_path):
        self.site_map_path = site_map_path
        if os.path.isfile(site_map_path):
            self.xml_tree = etree.parse(site_map_path).getroot()
        else:
            self.xml_tree = etree.Element('urlset', xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")

    def add_url(self, uri):
        if self.has_duplicate(uri): return
        url = etree.Element('url')
        loc = etree.Element('loc')
        lastmodify = etree.Element('lastmod')
        loc.text = uri
        lastmodify.text = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        url.append(loc)
        url.append(lastmodify)
        self.xml_tree.append(url)

    def has_duplicate(self, uri):
        for child in self.xml_tree:
            if child[0].text == uri: return True
        return False

    def generate(self):
        with open(self.site_map_path, 'wb') as f:
            xml_data = etree.tostring(self.xml_tree, encoding='utf-8', pretty_print=True)
            f.write(xml_data)
        # after generate, trigger google to update
        # requests.get('http://www.google.com/ping?sitemap=https://movie.insar.com.cn/sitemap.xml')
        client.put_object_from_local_file(
            Bucket='movie-1251435248', LocalFilePath='site/sitemap.xml'.format(html_name), Key='sitemap.xml')


def get_string_to_sign(params):
    s = "GETcdn.api.qcloud.com/v2/index.php?"
    query_str = "&".join("%s=%s" % (k, params[k]) for k in sorted(params))
    return s + query_str


def sign_str(key, s, method):
    hmac_str = hmac.new(key.encode("utf8"), s.encode("utf8"), method).digest()
    return base64.b64encode(hmac_str)


def refresh_cdn_sitemap():
    params = {
        'Action': 'RefreshCdnUrl',
        'Timestamp': int(time.time()),
        'Nonce': 59485,
        'SecretId': 'AKIDMnxCUBusqPdqCwrALvDwxW1TEcWxlUn6',
        'urls.0': 'http://movie.insar.com.cn/sitemap.xml'
    }

    s = get_string_to_sign(params)
    params["Signature"] = sign_str('JdATOWS43FXKwZCZX4iyaElMzk788LWD', s, hashlib.sha1)
    return requests.get("https://cdn.api.qcloud.com/v2/index.php", params=params)


if __name__ == '__main__':
    site_map = SiteMap('site/sitemap.xml')
    movie_template = get_jinja_template('template/movie.html')
    movies = fetch_latest_movies(100)
    for movie in movies:
        html = movie_template.render(movie=movie)
        html_name = "movie-{}-{}.html".format(re.sub(r'[^\w]', '', movie['title']), movie['id'])
        generate_local_html(html_name, html)
        site_map.add_url('http://movie.insar.com.cn/movie/{}'.format(html_name))
        client.put_object_from_local_file(Bucket='movie-1251435248', LocalFilePath='site/movie/{}'.format(html_name), Key="movie/{}".format(html_name))
    site_map.generate()
    refresh_cdn_sitemap()
